#include <iostream>
#include <thread>
#include <chrono>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <cstring>
#include <nlohmann/json.hpp>
#include <unordered_map>
#include <string>

using json = nlohmann::json;
using namespace std;



class ReadSpotData{
public:
    ReadSpotData(const std::vector<std::string> & instIds):pairs(instIds){
        key_t key = ftok("SHM_BinanceSpotData", 65);
        int shmid = shmget(key, sizeof(SharedData), 0666 | IPC_CREAT);
        if (shmid < 0) {
            perror("shmget failed");
            return;
        }
        shmData = (SharedData*) shmat(shmid,(void*)0,0); 

        for(int i=0;i<pairs.size();i++){
            pair_to_index[pairs[i]] = i;
        }
    }

    double price(const std::string &symbol, const std::string &type){
        int index = pair_to_index[symbol];
        pthread_mutex_lock(&shmData->coins[index].mutex);
        json json_data = json::parse(shmData->coins[index].book);
        pthread_mutex_unlock(&shmData->coins[index].mutex);
        double p = json_data[type].get<double>();
        return p;
    }
private:
    struct Coin{
        pthread_mutex_t mutex;
        char book[256];
    };
    struct SharedData {
        Coin coins[100]; 
    };
    int shmid;
    SharedData* shmData;
    std::vector<std::string> pairs;
    unordered_map<std::string,int> pair_to_index;
};

int main() {

    std::vector<std::string> instIds = {"BTCUSDT","ETHUSDT","BNBUSDT","SOLUSDT","DOGEUSDT","ADAUSDT",
    "BTCUSDC","ETHUSDC","BNBUSDC","SOLUSDC","DOGEUSDC","ADAUSDC","ETHBTC","BNBBTC","BNBETH","SOLBTC",
    "SOLETH","DOGEBTC","ADABTC","ADAETH"};

    ReadSpotData rd(instIds);

    while(true){
        double a = rd.price("BNBUSDT","A");
        double b = rd.price("BNBBTC","B");
        double c = rd.price("BTCUSDT","B");
        std::cout<<a/b/c<<std::endl;
        std::cout<<"BNBUSDT:"<<a<<" BNBBTC:"<<b<<" BTCUSDT:"<<c<<std::endl;
        std::this_thread::sleep_for(std::chrono::seconds(2));
    }
    
    return 0;
}
